import time
from flask import Blueprint, request, jsonify, current_app, render_template, session
from .models import db, User
from .forms import LoginForm, RegisterForm, ForgotPasswordForm, SetPasswordForm
from .utils import *
from flask_login import login_user, logout_user, login_required
from .emailSender import EmailSender


auth_bp = Blueprint('auth', __name__, url_prefix='/auth')
page_bp = Blueprint('pages', __name__)


# 页面路由
@page_bp.route('/login', methods=['GET'])
def login_page():
    """登录页面"""
    # 生成并存储验证码
     # 获取当前时间戳
    current_time = time.time()
    captcha_text = generate_captcha_text()
    session['captcha'] = {
            'text': captcha_text,
            'expire_time': current_time + current_app.config['CAPTCHA_EXPIRE_TIME']
        }
    form = LoginForm()
    return render_template('auth/login.html', captcha_text=captcha_text)

@page_bp.route('/logout', methods=['GET'])
@login_required
def logout_page():
    """退出登录页面"""
    logout_user()
    return render_template('auth/logout.html')

@page_bp.route('/register', methods=['GET'])
def register_page():
    """注册页面"""
    # 生成并存储验证码
    current_time = time.time()
    captcha_text = generate_captcha_text()
    session['captcha'] = {
            'text': captcha_text,
            'expire_time': current_time + current_app.config['CAPTCHA_EXPIRE_TIME']
        }
    form = RegisterForm()
    return render_template('auth/register.html', captcha_text=captcha_text)

@page_bp.route('/forgot-password', methods=['GET'])
def forgot_password_page():
    """忘记密码页面"""
    # 生成并存储验证码
    current_time = time.time()
    captcha_text = generate_captcha_text()
    session['captcha'] = {
            'text': captcha_text,
            'expire_time': current_time + current_app.config['CAPTCHA_EXPIRE_TIME']
        }
    form = ForgotPasswordForm()
    return render_template('auth/forgot_password.html', captcha_text=captcha_text)
@page_bp.route('/captcha')
def captcha():
    """生成验证码图片"""
    # 生成验证码文本
    current_time = time.time()
    captcha_text = generate_captcha_text()
    session['captcha'] = {
        'text': captcha_text,
        'expire_time': current_time + current_app.config['CAPTCHA_EXPIRE_TIME']
    }
    
    img_io = generte_img(captcha_text)
    
    return img_io.getvalue(), 200, {
        'Content-Type': 'image/png',
        'Cache-Control': 'no-cache, no-store, must-revalidate',
        'Pragma': 'no-cache',
        'Expires': '0',
    }

# API路由
@auth_bp.route('/login', methods=['POST'])
def login():
    """登录API"""
    form = LoginForm()
    if not form.validate_on_submit():
        return jsonify(error=format_form_errors(form.errors)), 400
    
    username = sanitize_input(form.username.data)
    password = form.password.data
    ip = request.remote_addr

    if "@" in username:  # 邮箱登录
        user = User.query.filter_by(email=username).first()
    else:  # 用户名登录
        user = User.query.filter_by(username=username).first()
    
    
    # 验证码检查
    captcha_input = form.captcha.data.lower()
    # 获取session中的验证码
    stored_captcha = session.get('captcha', {})
    
    # 检查验证码是否有效
    res = validate_captcha(captcha_input,stored_captcha)
    if res:
        return res
    
    if not user or not user.check_password(password):
        log_security_event('LOGIN_FAILED', user, ip)
        if user:
            handle_failed_login(user, ip)
        return jsonify(error="用户名或密码错误"), 401
    
    if user.is_locked():
        return jsonify(error="账户已锁定，请稍后再试"), 403
    
    reset_login_attempts(user)
    login_user(user, remember=bool(form.remember.data))  # 登录用户
    log_security_event('LOGIN_SUCCESS', user, ip)
    
    # 这里生成访问令牌（实际实现需使用JWT等安全方案）
    return jsonify(token="secure-auth-token", message="登录成功")


@auth_bp.route('/register', methods=['POST'])
def register():
    """注册API"""
    form = RegisterForm()
    if not form.validate_on_submit():
        return jsonify(error=format_form_errors(form.errors)), 400

    
    # 验证码检查
    captcha_input = form.captcha.data.lower()
    # 获取session中的验证码
    stored_captcha = session.get('captcha', {})
    
    
    # 检查验证码是否有效
    res = validate_captcha(captcha_input,stored_captcha)
    if res:
        return res
    
    user = User(
        username=sanitize_input(form.username.data),
        email=sanitize_input(form.email.data)
    )
    user.set_password(form.password.data)
    
    try:
        db.session.add(user)
        db.session.commit()
        log_security_event('REGISTER_SUCCESS', user, request.remote_addr)
        return jsonify(message="注册成功"), 201
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(f"注册失败: {str(e)}")
        return jsonify(error="注册失败，请重试"), 500

@auth_bp.route('/forgot-password/sent-email', methods=['POST'])
def sent_email():
    """忘记密码API"""
    form = ForgotPasswordForm()
    if not form.validate_on_submit():
        return jsonify(error=format_form_errors(form.errors)), 400
    
    reset_code = session.get('reset_email_sent', {})
    if reset_code:
        if reset_code['retry_time'] > time.time():
            return jsonify(error=f"请勿重复发送邮件,{current_app.config['LOCKOUT_TIME']//60}分钟后重试！"), 400
    
     # 验证码检查
    captcha_input = form.captcha.data.lower()
    # 获取session中的验证码
    stored_captcha = session.get('captcha', {})

    sender = EmailSender(current_app.config['SMTP_SERVER'], current_app.config['SMTP_USER'], current_app.config['SMTP_PASSWORD'])
    
    
    # 检查验证码是否有效
    res = validate_captcha(captcha_input,stored_captcha)
    if res:
        return res
    
    email = sanitize_input(form.email.data)
    user = User.query.filter_by(email=email).first()
    
    if user:
        # 实际实现应发送密码重置邮件
        reset_code = generate_email_captcha(user)
        log_security_event('PASSWORD_RESET_REQUEST', user, request.remote_addr)
        # 记录日志但不实际发送邮件（演示目的）
        current_app.logger.info(f"Password reset code for {email}: {reset_code}")

        html_content = f"""
                    <html>
                        <body>
                            <h1>找回密码</h1>
                            <p>您的用户名为: <strong>{user.username}</strong></p>
                            <p>您的验证码为: <strong>{reset_code}</strong></p>
                            <p>有效期: <strong>{current_app.config['RESET_CODE_EXPIRE_TIME']//60}分钟</strong></p>
                        </body>
                    </html>
                    """
        
        sent_status = sender.send_email(
            recipients=[email],
            subject="密码重置",
            html=html_content,
        )

        session["reset_email_sent"] = {
            "reset_code": reset_code,
            "expire_time": time.time() + current_app.config['RESET_CODE_EXPIRE_TIME'],
            "retry_time": time.time() + current_app.config['LOCKOUT_TIME'],
        }
        if not sent_status:
            return jsonify(error="邮件发送失败，请稍后再试"), 500
    
    # 无论用户是否存在都返回相同信息（防止枚举攻击）
    return jsonify(message="验证码已发送，请注意查收，有效期{}分钟！".format(current_app.config['RESET_CODE_EXPIRE_TIME']//60)), 200

@auth_bp.route('/forgot-password/vaildate-email-captcha', methods=['POST'])
def vaildate_email_captcha():
    form = ForgotPasswordForm()
    if not form.validate_on_submit():
        return jsonify(error=format_form_errors(form.errors)), 400
    
    reset_code = session.get('reset_code', {})
    captcha_input = form.captcha.data
    if reset_code.get('reset_code') and reset_code.get('expire_time', 0) > time.time():
        # 验证码有效
        if reset_code['reset_code'] == captcha_input:
            return jsonify(message="验证码正确"), 200
        else:
            return jsonify(error="验证码错误"), 400
    else:
        return jsonify(error="验证码已过期"), 400



@auth_bp.route('/forgot-password/set-passwd', methods=['POST'])
def set_passwd():
    """设置密码API"""
    form = SetPasswordForm()
    if not form.validate_on_submit():
        return jsonify(error=format_form_errors(form.errors)), 400
    
    email = sanitize_input(form.email.data)
    user = User.query.filter_by(email=email).first()
    if user and user.check_password(form.password.data):
        return jsonify(error="新密码不能与旧密码相同"), 400
    if user:
        user.set_password(form.password.data)
        db.session.commit()
    else:
        return jsonify(error="用户不存在"), 400

    return jsonify(message="密码设置成功"), 200

